package cdbft

import (
	"blockchain/public/function"
)

type commitMessage struct {
	tradeHash [32]byte
	sign string
	nodeSeq int
}

func commit(nodeSeq int){
	var commit commitMessage
	commit.nodeSeq=nodeSeq
	commit.tradeHash=commitData(nodeSeq)
	commit.sign=function.SignHash(commit.tradeHash,nodeSeq)
	var flagCommitted =make(chan bool)
	go nodeSendCommitMessage(nodeSeq,flagCommitted,commit)
	<-flagCommitted
}

func nodeSendCommitMessage(nodeSeq int,flagCommitted chan bool,commit commitMessage){
	for i:=0;i<N/groupNum;i++{
		select {
		case chanRecCommit[i]<-commit:
			FlagCommitted[nodeSeq][i]<-true
			close(FlagCommitted[nodeSeq][i])
		default:
			FlagCommitted[nodeSeq][i]<-false
			close(FlagCommitted[nodeSeq][i])

		}
	}
	flagCommitted<-true
	close(flagCommitted)
}


func commitData(nodeSeq int)  [32]byte{
	var prepare [2*(N/groupNum)/3+1]prepareMessage
	var counter [(N/groupNum)*2/3+1]int
	var sameSeq [(N/groupNum)*2/3+1]int
	var hash [32]byte
	var prepareDate [(N/groupNum)] prepareMessage
	var state[(N/groupNum)] int//表示prepare消息状态，0未验证签名，1签名验证正确，2签名验证失败
	for i:=0;i<2*(N/groupNum)/3+1;i++{
		sameSeq[i]=-1
	}
	for i:=0;i<(N/groupNum);i++{
		state[i]=0
	}

	count:=0
	for data:=range chanRecPrepare[nodeSeq]{
		prepareDate[count] =data
		count++

	}
	for i:=0;i<(N/groupNum)*2/3+1;i++{
		if sameSeq[i]==-1{
			sameSeq[i]=i
			counter[i]=0
			for j:=i;j<2*(N/groupNum)/3+1;j++{
				if state[j]==0{
					res:=function.VerifySignHash(prepareDate[j].tradesHash,prepareDate[j].sign,prepareDate[j].nodeSeq)
					if res{
						prepare[j]=prepareDate[j]
						state[j]=1
					}else {
						state[j]=2
					}
				}
				if state[i]==1 && state[j]==1{
					if prepare[i].tradesHash==prepare[j].tradesHash{
						counter[i]++
						sameSeq[j]=i
					}
				}
				if counter[i]>(N/groupNum)/3{
					break
				}
			}
			if counter[i]>(N/groupNum)/3{
				break
			}
		}
	}

	for i:=0;i<(N/groupNum)*2/3+1;i++{
		if counter[i]>(N/groupNum)/3{
			hash=prepare[i].tradesHash
		}
	}
	return hash
}

/*func commitData(nodeSeq int)  [32]byte{
	var prepare [2*(N/groupNum)/3+1]prepareMessage
	var counter [(N/groupNum)*2/3+1]int
	var sameSeq [(N/groupNum)*2/3+1]int
	var hash [32]byte
	for i:=0;i<2*(N/groupNum)/3+1;i++{
		sameSeq[i]=-1
	}
	count:=0
	for data:=range chanRecPrepare[nodeSeq]{
		res:=function.VerifySignHash(data.tradesHash,data.sign,data.nodeSeq)
		if res{
			prepare[count]=data
			count++
		}
	}
	for i:=0;i<(N/groupNum)*2/3+1;i++{
		if sameSeq[i]==-1{
			sameSeq[i]=i
			counter[i]=1
			for j:=i+1;j<2*(N/groupNum)/3+1;j++{
				if prepare[i].tradesHash==prepare[j].tradesHash{
					counter[i]++
					sameSeq[j]=i
				}
			}
		}
	}

	for i:=0;i<(N/groupNum)*2/3+1;i++{
		if counter[i]>(N/groupNum)/3{
			hash=prepare[i].tradesHash
		}
	}
	return hash
}*/

